package main

import (
	"fmt"
	"html/template"
	"io"
	"log"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

type FileDesc struct {
	Fid   uint32
	Title string
	Bid   uint32
	Bname string
}
type TreeAdmin struct {
	Txt                          string
	Gid                          uint32
	Publish                      int
	Nfiles                       []FileDesc
	Pfiles                       []FileDesc
	Pn, Pn_pre, Pn_next, Pn_last int
	Prefix                       string
}

// 管理员和作者首页
func (self *Site) HandleAdmin(resp http.ResponseWriter, req *http.Request) {
	var pub, pn int
	var err error
	p1 := GetOne(req, "u")
	pub, err = strconv.Atoi(p1)
	if err != nil {
		pub = 0
	}
	p2 := GetOne(req, "p")
	pn, err = strconv.Atoi(p2)
	if err != nil {
		pn = 1
	} else if pn < 1 {
		pn = 1
	}
	var req_str string = "未登录"

	u1 := self.ValidLogined(resp, req)
	if u1 != nil {
		req_str = "登录用户：" + u1.Uname
	}
	var tree2 TreeAdmin
	tree2.Publish = pub
	var count1 int
	if u1 != nil {
		tree2.Gid = u1.Gid
		if pub == 0 {
			fl1 := self.GetFilesByUID(u1.Uid, uint32((pn-1)*20), false)
			count1 = self.GetFileNumByUID(u1.Uid, false)
			for _, v := range fl1 {
				tree2.Nfiles = append(tree2.Nfiles, FileDesc{v.Fid, v.Title, v.Bid, self.GetBlockName(v.Bid)})
			}
		} else {
			fl1 := self.GetFilesByUID(u1.Uid, uint32((pn-1)*20), true)
			count1 = self.GetFileNumByUID(u1.Uid, true)
			for _, v := range fl1 {
				tree2.Pfiles = append(tree2.Pfiles, FileDesc{v.Fid, v.Title, v.Bid, self.GetBlockName(v.Bid)})
			}
		}
	} else {
		tree2.Gid = 99
	}
	var psize1 int = 20
	var pcount1 int
	tree2.Pn = pn
	tree2.Pn_pre = pn - 1
	pcount1 = count1 / psize1
	if count1%psize1 > 0 {
		pcount1++
	}
	tree2.Pn_last = pcount1
	if pcount1 > tree2.Pn {
		tree2.Pn_next = tree2.Pn + 1
	} else {
		tree2.Pn_next = tree2.Pn
	}
	tree2.Txt = req_str
	resp.WriteHeader(200)
	tree2.Prefix = self.Prefix
	err1 := self.ExecTemplateWithFuncs(path.Join("templates", "admin.tmpl"), "", resp, tree2, self.FuncMap)
	if err1 != nil {
		log.Println(err1)
	}
}

// 管理员和作者登录页面
func (self *Site) HandleLogin(resp http.ResponseWriter, req *http.Request) {
	var mtree map[string]interface{} = make(map[string]interface{})
	mtree["Prefix"] = self.Prefix
	var cookie2 http.Cookie
	u1 := self.ValidLogin(resp, req)
	if u1 == nil {
		u2 := self.ValidLogined(resp, req)
		if u2 == nil {
			cookie2.Name = "login"
			cookie2.Value = req.RemoteAddr
			http.SetCookie(resp, &cookie2)

			resp.WriteHeader(200)
			mtree["title"] = "登录"
			mtree["mode"] = 0
			err1 := self.ExecTemplateWithFuncs(path.Join("templates", "login.tmpl"), "", resp, mtree, self.FuncMap)
			if err1 != nil {
				log.Println(err1)
			}
			return
		} else {
			u1 = u2
		}
	}
	cookie2.Name = "logined"
	ip1, _ := req.Cookie("login")
	cookie2.Value = strconv.Itoa(int(u1.Uid)) + "@" + HexMd5(ip1.Value+u1.Pwd_md5)
	http.SetCookie(resp, &cookie2)
	resp.WriteHeader(200)
	mtree["title"] = u1.Uname
	mtree["mode"] = 1
	err1 := self.ExecTemplateWithFuncs(path.Join("templates", "login.tmpl"), "", resp, mtree, self.FuncMap)
	if err1 != nil {
		log.Println(err1)
	}
}

// 注销
func (self *Site) HandleLogout(resp http.ResponseWriter, req *http.Request) {
	var cookie2 http.Cookie
	cookie2.Expires = time.Now()
	cookie2.Name = "logined"
	cookie2.Value = "0@0"
	http.SetCookie(resp, &cookie2)
	resp.WriteHeader(200)
	self.MyRedirect(resp, req.Referer())
}

// 管理员新增作者
func (self *Site) HandleAdduser(resp http.ResponseWriter, req *http.Request) {
	u0 := self.ValidLogined(resp, req)
	if u0 == nil {
		http.Redirect(resp, req, self.Prefix+"/authors", http.StatusMovedPermanently)
		return
	}
	if u0.Gid > 0 {
		http.Redirect(resp, req, self.Prefix+"/authors", http.StatusMovedPermanently)
		return
	}
	req.ParseForm()
	uname := req.FormValue("uname")
	shown := req.FormValue("shown")
	pwd_md5 := req.FormValue("pwd")
	group, err := strconv.Atoi(req.FormValue("group"))
	if err != nil || len(uname) == 0 {
		http.Redirect(resp, req, self.Prefix+"/authors", http.StatusMovedPermanently)
		return
	}
	self.AddUser(group, uname, shown, pwd_md5, GetIP(req.RemoteAddr))
	http.Redirect(resp, req, self.Prefix+"/authors", http.StatusMovedPermanently)
}

// 显示作者列表（GID=1）
func (self *Site) HandleAuthors(resp http.ResponseWriter, req *http.Request) {
	var mtree = make(map[string]interface{})
	var level uint32
	u0 := self.ValidLogined(resp, req)
	if u0 == nil {
		level = 99
	} else {
		level = u0.Gid
	}
	users := self.GetUsersByGid(1)
	mtree["level"] = level
	mtree["users"] = users
	mtree["Prefix"] = self.Prefix
	resp.WriteHeader(200)
	err1 := self.ExecTemplateWithFuncs(path.Join("templates", "authors.tmpl"), "", resp, mtree, self.FuncMap)
	if err1 != nil {
		log.Println(err1)
	}
}

// 显示板块列表
func (self *Site) HandleBlocks(resp http.ResponseWriter, req *http.Request) {
	var mtree = make(map[string]interface{})
	var level uint32
	u0 := self.ValidLogined(resp, req)
	if u0 == nil {
		self.MyRedirect(resp, self.Prefix+"/admin")
	} else if u0.Gid > 0 {
		self.MyRedirect(resp, self.Prefix+"/admin")
	}
	blks := self.GetBlocks()

	mtree["level"] = level
	mtree["blks"] = blks
	mtree["Prefix"] = self.Prefix
	resp.WriteHeader(200)
	err1 := self.ExecTemplateWithFuncs(path.Join("templates", "blocks.tmpl"), "", resp, mtree, self.FuncMap)
	if err1 != nil {
		log.Println(err1)
	}
}

// 新建板块
func (self *Site) HandleAddblock(resp http.ResponseWriter, req *http.Request) {
	u0 := self.ValidLogined(resp, req)
	if u0 == nil {
		http.Redirect(resp, req, self.Prefix+"/blocks", http.StatusMovedPermanently)
		return
	}
	if u0.Gid > 0 {
		http.Redirect(resp, req, self.Prefix+"/blocks", http.StatusMovedPermanently)
		return
	}
	req.ParseForm()
	name := req.FormValue("name")
	desc := req.FormValue("desc")
	self.AddBlock(name, desc)
	http.Redirect(resp, req, self.Prefix+"/blocks", http.StatusMovedPermanently)
}

// 新建文章
func (self *Site) HandleNewfile(resp http.ResponseWriter, req *http.Request) {
	var tree1 TreeEditor
	tree1.Prefix = self.Prefix
	u1 := self.ValidLogined(resp, req)
	if u1 == nil {
		http.Redirect(resp, req, self.Prefix+"/", http.StatusMovedPermanently)
		return
	}
	if u1.Gid != 1 {
		http.Redirect(resp, req, self.Prefix+"/", http.StatusMovedPermanently)
		return
	}
	tree1.Blocks = self.GetBlocks()
	tree1.Fid = int(self.AddFile(u1.Uid, GetIP(req.RemoteAddr)))
	cxt := fmt.Sprintf("*作者：* 无名氏\n\n*日期：*%s\n\n正文\n", GetDate("年", "月", "日"))
	tree1.File1 = FileReturn{1, GetDate("年", "月", "日"), cxt}
	resp.WriteHeader(200)
	err1 := self.ExecTemplateWithFuncs(path.Join("templates", "editor.tmpl"), "", resp, tree1, self.FuncMap)
	if err1 != nil {
		log.Println(err1)
	}
}

// ajax 保存文章，不发表（已发表的不改变状态）
func (self *Site) HandleSavefile(resp http.ResponseWriter, req *http.Request) {
	req.ParseForm()
	title1 := req.FormValue("title")
	bid1, _ := strconv.Atoi(req.FormValue("bid"))
	fid1, _ := strconv.Atoi(req.FormValue("fid"))
	md1 := req.FormValue("md_text")
	//fmt.Printf("T:%v\nBID:%v\nFID:%v\nTEXT:%v\n", title1, bid1, fid1, md1)
	err := self.UpdateFile(uint32(fid1), uint32(bid1), title1, md1, GetIP(req.RemoteAddr))
	resp.WriteHeader(200)
	if err == nil {
		resp.Write([]byte("已保存"))
	} else {
		resp.Write([]byte("保存失败"))
	}
}

// ajax 保存并且发表文章
func (self *Site) HandleSavepublish(resp http.ResponseWriter, req *http.Request) {
	req.ParseForm()
	title1 := req.FormValue("title")
	bid1, _ := strconv.Atoi(req.FormValue("bid"))
	fid1, _ := strconv.Atoi(req.FormValue("fid"))
	md1 := req.FormValue("md_text")
	//fmt.Printf("T:%v\nBID:%v\nFID:%v\nTEXT:%v\n", title1, bid1, fid1, md1)
	err := self.UpdateFilePublish(uint32(fid1), uint32(bid1), title1, md1, GetIP(req.RemoteAddr))
	resp.WriteHeader(200)
	if err == nil {
		resp.Write([]byte("已保存"))
	} else {
		log.Printf("HandleSavepublish: %v\n", err)
	}
}

type TreeEditor struct {
	Fid    int
	Blocks []Block
	Imgs   []ImgInfo
	File1  FileReturn
	Prefix string
}

// 编辑文章
func (self *Site) HandleEditfile(resp http.ResponseWriter, req *http.Request) {
	u1 := self.ValidLogined(resp, req)
	if u1 == nil {
		http.Redirect(resp, req, self.Prefix+"/", http.StatusMovedPermanently)
		return
	}
	if u1.Gid != 1 {
		http.Redirect(resp, req, self.Prefix+"/", http.StatusMovedPermanently)
		return
	}
	f := GetOne(req, "f")
	var fid int
	var err error
	fid, err = strconv.Atoi(f)
	if err != nil {
		http.Redirect(resp, req, self.Prefix+"/", http.StatusMovedPermanently)
		return
	}
	var tree1 TreeEditor
	tree1.Prefix = self.Prefix
	tree1.Blocks = self.GetBlocks()
	tree1.Imgs = self.GetImageByFID(fid)
	tree1.Fid = fid
	fc1 := self.GetFileByFID(uint32(fid))
	tree1.File1 = *fc1
	resp.WriteHeader(200)
	err1 := self.ExecTemplateWithFuncs(path.Join("templates", "editor.tmpl"), "", resp, tree1, self.FuncMap)
	if err1 != nil {
		log.Println(err1)
	}
}

// ajax 上传图片，返回信息到编辑器
func (self *Site) HandleUploadimg(resp http.ResponseWriter, req *http.Request) {
	u1 := self.ValidLogined(resp, req)
	if u1 == nil {
		return
	}
	if u1.Gid != 1 {
		return
	}
	r, err := req.MultipartReader()
	if err != nil {
		return
	}
	f, err := r.ReadForm(5 * 1024 * 1024)
	f1, ok := f.Value["fid"]
	var fid int
	if ok {
		fid, _ = strconv.Atoi(f1[0])
	}
	var result string
	if err == nil {
		if len(f.File) == 1 {
			v := f.File["photo"]
			if len(v) == 1 {
				if1, _ := v[0].Open()
				defer if1.Close()
				fields := strings.Split(v[0].Filename, ".")
				rands := self.Uniq.GetID()
				now1 := time.Now()
				yearmonth := fmt.Sprintf("/upimages/%v%v", now1.Year(), now1.Month())
				path0 := yearmonth + "/" + rands + "." + fields[len(fields)-1]
				os.MkdirAll(filepath.Join(self.StaticBase, yearmonth), os.ModePerm|os.ModeDir)
				of1, _ := os.Create(filepath.Join(self.StaticBase, path0))
				defer of1.Close()
				io.Copy(of1, if1)
				// images表中保存图片显示路径
				path1 := self.DocRoot() + path0
				self.AddImage(fid, path1, v[0].Filename)
				result = fmt.Sprintf("<option selected='selected' value='%v'>%v</option>", path1, v[0].Filename)
			}
		}
	}
	if len(result) > 0 {
		resp.WriteHeader(200)
		resp.Write([]byte(result))
	}
}

// ajax 设置文章发表状态
func (self *Site) HandlePublish(resp http.ResponseWriter, req *http.Request) {
	u1 := self.ValidLogined(resp, req)
	if u1 == nil {
		return
	}
	if u1.Gid != 1 {
		return
	}
	f := GetOne(req, "f")
	if len(f) == 0 {
		return
	}
	fid, err := strconv.Atoi(f)
	if err != nil {
		return
	}
	err = self.PublishFile(uint32(fid), u1.Uid)
	if err == nil {
		resp.WriteHeader(200)
		resp.Write([]byte("已发表"))
	}
}

// ajax 删除本用户发表、编辑的文章
func (self *Site) HandleDel(resp http.ResponseWriter, req *http.Request) {
	u1 := self.ValidLogined(resp, req)
	if u1 == nil {
		return
	}
	if u1.Gid != 1 {
		return
	}
	f := GetOne(req, "f")
	if len(f) == 0 {
		return
	}
	fid, err := strconv.Atoi(f)
	if err != nil {
		return
	}
	err = self.DelFile(fid)
	if err == nil {
		resp.WriteHeader(200)
		resp.Write([]byte("已删除"))
	}
}

// ajax 板块重命名
func (self *Site) HandleRenameblock(resp http.ResponseWriter, req *http.Request) {
	u0 := self.ValidLogined(resp, req)
	if u0 == nil {
		return
	}
	if u0.Gid > 0 {
		return
	}
	req.ParseForm()
	name := req.FormValue("bname")
	bid, err := strconv.Atoi(req.FormValue("bid"))
	if err == nil && len(name) > 0 {
		self.RenameBlock(uint32(bid), name)
		resp.WriteHeader(200)
		resp.Write([]byte("修改成功"))
	}
}

//重定向
func (self *Site) MyRedirect(resp http.ResponseWriter, url1 string) {
	t1, err1 := template.ParseFiles(path.Join(self.DynBase, "templates", "redirect.tmpl"))
	if err1 != nil {
		log.Println(err1)
		return
	}
	resp.WriteHeader(200)
	err1 = t1.Execute(resp, url1)
	if err1 != nil {
		log.Println(err1)
	}
}

//保存新的评论
func (self *Site) HandleSavediscuss(resp http.ResponseWriter, req *http.Request) {
	var u2 = self.ValidLogin(resp, req)
	if u2 == nil {
		u2 = self.ValidLogined(resp, req)
		if u2 == nil {
			self.MyRedirect(resp, req.Referer())
			return
		}
	}
	if u2.Gid > 2 {
		self.MyRedirect(resp, req.Referer())
		return
	}
	// set cookie logined
	var cookie2 http.Cookie
	cookie2.Name = "logined"
	ip1, _ := req.Cookie("login")
	cookie2.Value = strconv.Itoa(int(u2.Uid)) + "@" + HexMd5(ip1.Value+u2.Pwd_md5)
	http.SetCookie(resp, &cookie2)

	req.ParseForm()
	fid1, _ := strconv.Atoi(req.FormValue("fid"))
	discus1 := req.FormValue("discus")
	if fid1 > 0 && len(discus1) > 2 {
		self.SaveDiscus(fid1, int(u2.Uid), u2.Showname, discus1, GetIP(req.RemoteAddr))
	}
	self.MyRedirect(resp, req.Referer())
}

//注册评论员用户输入信息页面
func (self *Site) HandleReguser(resp http.ResponseWriter, req *http.Request) {
	var mtree = make(map[string]interface{})
	mtree["Prefix"] = self.Prefix
	u2 := self.ValidLogined(resp, req)
	if u2 != nil {
		resp.WriteHeader(200)
		mtree["msg"] = "你已登录"
		err1 := self.ExecTemplateWithFuncs(path.Join("templates", "saveuser.tmpl"), "", resp, mtree, self.FuncMap)
		if err1 != nil {
			log.Println(err1)
			self.MyRedirect(resp, self.Prefix+"/")
		}
		return
	}
	resp.WriteHeader(200)
	err1 := self.ExecTemplateWithFuncs(path.Join("templates", "reguser.tmpl"), "", resp, mtree, self.FuncMap)
	if err1 != nil {
		log.Println(err1)
		self.MyRedirect(resp, self.Prefix+"/")
	}
}

//注册评论员用户
func (self *Site) HandleSaveuser(resp http.ResponseWriter, req *http.Request) {
	var mtree = make(map[string]interface{})
	mtree["Prefix"] = self.Prefix
	req.ParseForm()
	uname := req.FormValue("uname")
	shown := req.FormValue("shown")
	pwd_md5 := req.FormValue("pwd")
	if len(uname) == 0 {
		self.MyRedirect(resp, self.Prefix+"/reguser")
		return
	}
	self.AddUser(2, uname, shown, pwd_md5, GetIP(req.RemoteAddr))
	mtree["msg"] = "注册成功"
	resp.WriteHeader(200)
	err1 := self.ExecTemplateWithFuncs(path.Join("templates", "saveuser.tmpl"), "", resp, mtree, self.FuncMap)
	if err1 != nil {
		log.Println(err1)
		self.MyRedirect(resp, self.Prefix+"/")
	}
}

// ajax 登录用户修改自己的称呼
func (self *Site) HandleNewname(resp http.ResponseWriter, req *http.Request) {
	req.ParseForm()
	shown := req.FormValue("s")
	if len(shown) == 0 {
		return
	}
	u2 := self.ValidLogined(resp, req)
	if u2 == nil {
		return
	}
	self.UpdateShowname(int(u2.Uid), shown)
	resp.WriteHeader(200)
	resp.Write([]byte("修改成功"))
}

//登录用户修改自己的密码，跳转回原来的页面
func (self *Site) HandleMynewpass(resp http.ResponseWriter, req *http.Request) {
	req.ParseForm()
	pwd_md5 := req.FormValue("pwd")
	if len(pwd_md5) != 32 {
		self.MyRedirect(resp, req.Referer())
		return
	}
	u2 := self.ValidLogined(resp, req)
	if u2 == nil {
		return
	}
	self.UpdatePass(int(u2.Uid), pwd_md5)
	//更新 Cookie
	var cookie2 http.Cookie
	cookie2.Name = "logined"
	ip1, _ := req.Cookie("login")
	cookie2.Value = strconv.Itoa(int(u2.Uid)) + "@" + HexMd5(ip1.Value+pwd_md5)
	http.SetCookie(resp, &cookie2)
	self.MyRedirect(resp, req.Referer())
}

// ajax 管理员修改一般用户的密码
func (self *Site) HandleModifyuserpass(resp http.ResponseWriter, req *http.Request) {
	u0 := self.ValidLogined(resp, req)
	if u0 == nil {
		return
	}
	if u0.Gid > 0 {
		return
	}
	req.ParseForm()
	uid1, _ := strconv.Atoi(req.FormValue("uid"))
	pwd_md5 := req.FormValue("pwd")
	if uid1 == 0 {
		return
	}
	self.UpdatePass(uid1, pwd_md5)
	resp.WriteHeader(200)
	resp.Write([]byte("修改成功"))
}

type TreeUserinfo struct {
	BackUrl  string
	Showname string
	Prefix   string
}

func (self *Site) HandleUserinfo(resp http.ResponseWriter, req *http.Request) {
	u0 := self.ValidLogined(resp, req)
	if u0 == nil {
		self.MyRedirect(resp, req.Referer())
		return
	}
	var tree1 TreeUserinfo
	tree1.Prefix = self.Prefix
	if u0.Gid < 2 {
		tree1 = TreeUserinfo{self.Prefix + "/admin", u0.Showname, self.Prefix}
	} else {
		tree1 = TreeUserinfo{self.Prefix + "/", u0.Showname, self.Prefix}
	}
	resp.WriteHeader(200)
	err1 := self.ExecTemplateWithFuncs(path.Join("templates", "userinfo.tmpl"), "", resp, tree1, self.FuncMap)
	if err1 != nil {
		log.Println(err1)
		self.MyRedirect(resp, req.Referer())
	}
}
func GetOne(req *http.Request, name string) string {
	v1, ok := req.URL.Query()[name]
	if ok {
		return v1[0]
	} else {
		return ""
	}
}
func (self *Site) HandleAuthorsearch(resp http.ResponseWriter, req *http.Request) {
	u1 := self.ValidLogined(resp, req)
	if u1 == nil {
		self.MyRedirect(resp, self.Prefix+"/admin")
		return
	}
	var tree1 TreeSearch
	tree1.Prefix = self.Prefix
	tree1.K = GetOne(req, "k")
	var pn int
	var err error
	p1 := GetOne(req, "p")
	pn, err = strconv.Atoi(p1)
	if err != nil {
		pn = 1
	}
	if pn == 0 {
		pn = 1
	}
	var psize1 int = 20
	tree1.Flist = self.SearchFiles(tree1.K, psize1, (pn-1)*psize1)
	count1 := self.SearchCount(tree1.K)
	// calculate pages
	tree1.Pn = pn
	tree1.Pn_pre = pn - 1
	pcount1 := count1 / psize1
	if count1%psize1 > 0 {
		pcount1++
	}
	tree1.Pn_last = pcount1
	if pcount1 > tree1.Pn {
		tree1.Pn_next = tree1.Pn + 1
	} else {
		tree1.Pn_next = tree1.Pn
	}
	//render
	resp.WriteHeader(200)
	err1 := self.ExecTemplateWithFuncs(path.Join("templates", "authorsearch.tmpl"), "", resp, tree1, self.FuncMap)
	if err1 != nil {
		log.Println(err1)
	}
}
